package org.owasp.esapi.logging.appender;

import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.times;
import static org.mockito.Mockito.verify;
import static org.mockito.Mockito.verifyNoMoreInteractions;
import static org.powermock.api.mockito.PowerMockito.mockStatic;
import static org.powermock.api.mockito.PowerMockito.when;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpSession;

import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.TestName;
import org.junit.runner.RunWith;
import org.mockito.ArgumentMatchers;
import org.owasp.esapi.Authenticator;
import org.owasp.esapi.ESAPI;
import org.owasp.esapi.Randomizer;
import org.owasp.esapi.User;
import org.powermock.core.classloader.annotations.PowerMockIgnore;
import org.powermock.core.classloader.annotations.PrepareForTest;
import org.powermock.modules.junit4.PowerMockRunner;

@RunWith(PowerMockRunner.class)
@PrepareForTest({ESAPI.class})
@PowerMockIgnore("javax.security.*") //Required since User extends javax.security.Principal
public class UserInfoSupplierTest {
    private static final String ESAPI_SESSION_ATTR = "ESAPI_SESSION";

    @Rule
    public TestName testName = new TestName();

    private Authenticator mockAuth;
    private User mockUser;

    @Before
    public void before() throws Exception {
        mockAuth =mock(Authenticator.class);
        mockUser =mock(User.class);

        mockStatic(ESAPI.class);
        when(ESAPI.class, "authenticator").thenReturn(mockAuth);

        when(mockUser.getAccountName()).thenReturn(testName.getMethodName() + "-USER");


        when(mockAuth.getCurrentUser()).thenReturn(mockUser);
    }

    @Test
    public void testHappyPath() throws Exception {
        UserInfoSupplier uis = new UserInfoSupplier();
        uis.setLogUserInfo(true);
        String result = uis.get();

        assertEquals(testName.getMethodName() + "-USER", result);

        verify(mockAuth,times(1)).getCurrentUser();
        verify(mockUser,times(1)).getAccountName();

        verifyNoMoreInteractions(mockAuth, mockUser);
    }

    @Test
    public void testLogUserOff() {
        UserInfoSupplier uis = new UserInfoSupplier();
        uis.setLogUserInfo(false);
        String result = uis.get();

        assertTrue(result.isEmpty());
        verify(mockAuth,times(1)).getCurrentUser();

        verifyNoMoreInteractions(mockAuth, mockUser);
    }

    @Test
    public void testLogUserNull() {
        when(mockAuth.getCurrentUser()).thenReturn(null);
        UserInfoSupplier uis = new UserInfoSupplier();
        uis.setLogUserInfo(true);
        String result = uis.get();

        assertEquals("#ANONYMOUS#", result);

        verify(mockAuth,times(1)).getCurrentUser();

        verifyNoMoreInteractions(mockAuth,  mockUser);
    }

}